home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / mac / DirectX SDK / DXSDK / samples / Multimedia / DirectPlay / Tutorials / Tut04_Connect / Connect.cpp next >
C/C++ Source or Header  |  2001-10-08  |  19KB  |  596 lines

  1. //----------------------------------------------------------------------------
  2. // File: Connect.cpp
  3. //
  4. // Desc: This simple program builds upon the last tutorial and adds connecting 
  5. //       to a host
  6. //
  7. // Copyright (c) 2000-2001 Microsoft Corp. All rights reserved.
  8. //-----------------------------------------------------------------------------
  9. #define INITGUID
  10. #define _WIN32_DCOM
  11. #include <stdio.h>
  12. #include <dplay8.h>
  13.  
  14.  
  15.  
  16. //-----------------------------------------------------------------------------
  17. // App specific structures 
  18. //-----------------------------------------------------------------------------
  19. struct HOST_NODE
  20. {
  21.     DPN_APPLICATION_DESC*   pAppDesc;
  22.     IDirectPlay8Address*    pHostAddress;
  23.     WCHAR*                  pwszSessionName;
  24.  
  25.     HOST_NODE*              pNext;
  26. };
  27.  
  28.  
  29. //-----------------------------------------------------------------------------
  30. // Global variables
  31. //-----------------------------------------------------------------------------
  32. IDirectPlay8Peer*                   g_pDP               = NULL;
  33. IDirectPlay8Address*                g_pDeviceAddress    = NULL;
  34. IDirectPlay8Address*                g_pHostAddress      = NULL;
  35. BOOL                                g_bHost;
  36. HOST_NODE*                          g_pHostList         = NULL;
  37. CRITICAL_SECTION                    g_csHostList;
  38.  
  39.  
  40. // This GUID allows DirectPlay to find other instances of the same game on
  41. // the network.  So it must be unique for every game, and the same for 
  42. // every instance of that game.  // // {A8F02BED-B09A-4911-A1CD-DB02578B9C8F}
  43. GUID g_guidApp = { 0xa8f02bed, 0xb09a, 0x4911, { 0xa1, 0xcd, 0xdb, 0x2, 0x57, 0x8b, 0x9c, 0x8f } };
  44.  
  45.  
  46. //-----------------------------------------------------------------------------
  47. // Function-prototypes
  48. //-----------------------------------------------------------------------------
  49. HRESULT WINAPI DirectPlayMessageHandler(PVOID pvUserContext, DWORD dwMessageId, PVOID pMsgBuffer);
  50. BOOL    IsServiceProviderValid(const GUID* pGuidSP);
  51. HRESULT InitDirectPlay();
  52. HRESULT CreateDeviceAddress();
  53. HRESULT CreateHostAddress(WCHAR* pwszHost);
  54. HRESULT HostSession();
  55. HRESULT EnumDirectPlayHosts();
  56. HRESULT ConnectToSession();
  57. void    CleanupDirectPlay();
  58.  
  59.  
  60. //-----------------------------------------------------------------------------
  61. // Miscellaneous helper functions
  62. //-----------------------------------------------------------------------------
  63. #define SAFE_DELETE(p)          {if(p) {delete (p);     (p)=NULL;}}
  64. #define SAFE_DELETE_ARRAY(p)    {if(p) {delete[] (p);   (p)=NULL;}}
  65. #define SAFE_RELEASE(p)         {if(p) {(p)->Release(); (p)=NULL;}}
  66.  
  67. #define USER_HOST       1
  68. #define USER_CONNECT    2
  69. #define USER_EXIT       1
  70.  
  71.  
  72.  
  73.  
  74. //-----------------------------------------------------------------------------
  75. // Name: main()
  76. // Desc: Entry point for the application.  
  77. //-----------------------------------------------------------------------------
  78. int main(int argc, char* argv[], char* envp[])
  79. {
  80.     HRESULT hr;
  81.     int     iUserChoice;
  82.  
  83.     // Init COM so we can use CoCreateInstance
  84.     CoInitializeEx(NULL, COINIT_MULTITHREADED);
  85.  
  86.     // Init the DirectPlay system
  87.     if( FAILED( hr = InitDirectPlay() ) )
  88.     {
  89.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  90.         goto LCleanup;
  91.     }
  92.  
  93.     InitializeCriticalSection(&g_csHostList);
  94.  
  95.     // Get the necessary user input on whether they are hosting or connecting
  96.     do
  97.     {
  98.         printf("Please select one.\n1.  Host\n2.  Connect\n");
  99.         scanf("%d", &iUserChoice);
  100.     } while (iUserChoice != USER_HOST && iUserChoice != USER_CONNECT);
  101.  
  102.  
  103.     if( FAILED( hr = CreateDeviceAddress() ) )
  104.     {
  105.         printf("Failed CreatingDeviceAddress:  0x%X\n", hr);
  106.         goto LCleanup;
  107.     }
  108.  
  109.     if( iUserChoice == USER_HOST)
  110.     {
  111.         if( FAILED( hr = HostSession() ) )
  112.         {
  113.             printf("Failed Hosting:  0x%X\n", hr);
  114.             goto LCleanup;
  115.         }
  116.     }
  117.     else
  118.     {
  119.         if( FAILED( hr = EnumDirectPlayHosts() ) )
  120.         {
  121.             printf("Failed Enumerating Host:  0x%X\n", hr);
  122.             goto LCleanup;
  123.         }
  124.  
  125.         if( FAILED( hr = ConnectToSession() ) )
  126.         {
  127.             printf("Failed Connect to Host:  0x%X\n", hr);
  128.             goto LCleanup;
  129.         }
  130.         else
  131.         {
  132.             printf("\nConnection Successful.\n");
  133.         }
  134.     }
  135.  
  136.     // Present User with Choices
  137.     do
  138.     {
  139.         printf("Please select one.\n1.  Exit\n");
  140.         scanf("%d", &iUserChoice);
  141.     } while (iUserChoice != USER_EXIT);
  142.  
  143.  
  144. LCleanup:
  145.     CleanupDirectPlay();
  146.  
  147.     // Cleanup COM
  148.     CoUninitialize();
  149.  
  150.     return 0;
  151. }
  152.  
  153.  
  154.  
  155.  
  156. //-----------------------------------------------------------------------------
  157. // Name: InitDirectPlay()
  158. // Desc: Initialize DirectPlay
  159. //-----------------------------------------------------------------------------
  160. HRESULT InitDirectPlay()
  161. {
  162.     HRESULT hr = S_OK;
  163.  
  164.     // Create the IDirectPlay8Peer Object
  165.     if( FAILED( hr = CoCreateInstance(CLSID_DirectPlay8Peer, NULL, 
  166.                                     CLSCTX_INPROC_SERVER,
  167.                                     IID_IDirectPlay8Peer, 
  168.                                     (LPVOID*) &g_pDP ) ) )
  169.     {
  170.         printf("Failed Creating the IDirectPlay8Peer Object:  0x%X\n", hr);
  171.         goto LCleanup;
  172.     }
  173.  
  174.     // Init DirectPlay
  175.     if( FAILED( hr = g_pDP->Initialize(NULL, DirectPlayMessageHandler, 0 ) ) )
  176.     {
  177.         printf("Failed Initializing DirectPlay:  0x%X\n", hr);
  178.         goto LCleanup;
  179.     }
  180.     
  181.     // Ensure that TCP/IP is a valid Service Provider
  182.     if( FALSE == IsServiceProviderValid(&CLSID_DP8SP_TCPIP ) )
  183.     {
  184.         hr = E_FAIL;
  185.         printf("Failed validating CLSID_DP8SP_TCPIP");
  186.         goto LCleanup;
  187.     }
  188.  
  189. LCleanup:
  190.     return hr;
  191. }
  192.  
  193.  
  194.  
  195.  
  196. //-----------------------------------------------------------------------------
  197. // Name: IsServiceProviderValid()
  198. // Desc: Return TRUE if the service provider is valid
  199. //-----------------------------------------------------------------------------
  200. BOOL IsServiceProviderValid(const GUID* pGuidSP)
  201. {
  202.     HRESULT                     hr;
  203.     DPN_SERVICE_PROVIDER_INFO*  pdnSPInfo = NULL;
  204.     DWORD                       dwItems   = 0;
  205.     DWORD                       dwSize    = 0;
  206.  
  207.     hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, NULL, &dwSize, &dwItems, 0);
  208.  
  209.     if( hr != DPNERR_BUFFERTOOSMALL)
  210.     {
  211.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  212.         goto LCleanup;
  213.     }
  214.  
  215.     pdnSPInfo = (DPN_SERVICE_PROVIDER_INFO*) new BYTE[dwSize];
  216.  
  217.     if( FAILED( hr = g_pDP->EnumServiceProviders(&CLSID_DP8SP_TCPIP, NULL, pdnSPInfo, &dwSize, &dwItems, 0 ) ) )
  218.     {
  219.         printf("Failed Enumerating Service Providers:  0x%x\n", hr);
  220.         goto LCleanup;
  221.     }
  222.  
  223.     // There are no items returned so the requested SP is not available
  224.     if( dwItems == 0)
  225.     {
  226.         hr = E_FAIL;
  227.     }
  228.  
  229. LCleanup:
  230.     SAFE_DELETE_ARRAY(pdnSPInfo);
  231.     
  232.     if( SUCCEEDED(hr) )
  233.         return TRUE;
  234.     else
  235.         return FALSE;
  236. }
  237.  
  238.  
  239.  
  240.  
  241. //-----------------------------------------------------------------------------
  242. // Name: DirectPlayMessageHandler
  243. // Desc: Handler for DirectPlay messages.  This tutorial only responds to the
  244. //       DPN_MSGID_ENUM_HOSTS_RESPONSE message.
  245. //-----------------------------------------------------------------------------
  246. HRESULT WINAPI DirectPlayMessageHandler( PVOID pvUserContext, DWORD dwMessageId, 
  247.                                          PVOID pMsgBuffer )
  248. {
  249.     HRESULT hr = S_OK;
  250.  
  251.     switch (dwMessageId)
  252.     {
  253.     case DPN_MSGID_ENUM_HOSTS_RESPONSE:
  254.         {
  255.             PDPNMSG_ENUM_HOSTS_RESPONSE     pEnumHostsResponseMsg;
  256.             const DPN_APPLICATION_DESC*     pAppDesc;
  257.             HOST_NODE*                      pHostNode = NULL;
  258.             WCHAR*                          pwszSession = NULL;
  259.  
  260.             pEnumHostsResponseMsg = (PDPNMSG_ENUM_HOSTS_RESPONSE) pMsgBuffer;
  261.             pAppDesc = pEnumHostsResponseMsg->pApplicationDescription;
  262.  
  263.             // Insert each host response if it isn't already present
  264.             EnterCriticalSection(&g_csHostList);
  265.  
  266.             for (pHostNode = g_pHostList; pHostNode; pHostNode = pHostNode->pNext)
  267.             {
  268.                 if( pAppDesc->guidInstance == pHostNode->pAppDesc->guidInstance)
  269.                 {
  270.                     // This host is already in the list
  271.                     pHostNode = NULL;
  272.                     goto Break_ENUM_HOSTS_RESPONSE;
  273.                 }
  274.             }
  275.  
  276.             // This host session is not in the list then so insert it.
  277.             pHostNode = new HOST_NODE;
  278.             if( pHostNode == NULL)
  279.             {
  280.                 goto Break_ENUM_HOSTS_RESPONSE;
  281.             }
  282.  
  283.             ZeroMemory(pHostNode, sizeof(HOST_NODE));
  284.  
  285.             // Copy the Host Address
  286.             if( FAILED( pEnumHostsResponseMsg->pAddressSender->Duplicate(&pHostNode->pHostAddress ) ) )
  287.             {
  288.                 goto Break_ENUM_HOSTS_RESPONSE;
  289.             }
  290.  
  291.             pHostNode->pAppDesc = new DPN_APPLICATION_DESC;
  292.  
  293.             if( pHostNode == NULL)
  294.             {
  295.                 goto Break_ENUM_HOSTS_RESPONSE;
  296.             }
  297.  
  298.             ZeroMemory(pHostNode->pAppDesc, sizeof(DPN_APPLICATION_DESC));
  299.             memcpy(pHostNode->pAppDesc, pAppDesc, sizeof(DPN_APPLICATION_DESC));
  300.  
  301.             // Null out all the pointers we aren't copying
  302.             pHostNode->pAppDesc->pwszSessionName = NULL;
  303.             pHostNode->pAppDesc->pwszPassword = NULL;
  304.             pHostNode->pAppDesc->pvReservedData = NULL;
  305.             pHostNode->pAppDesc->dwReservedDataSize = 0;
  306.             pHostNode->pAppDesc->pvApplicationReservedData = NULL;
  307.             pHostNode->pAppDesc->dwApplicationReservedDataSize = 0;
  308.             
  309.             if( pAppDesc->pwszSessionName)
  310.             {
  311.                 pwszSession = new WCHAR[wcslen(pAppDesc->pwszSessionName) + 1];
  312.                 
  313.                 if( pwszSession)
  314.                 {
  315.                     wcscpy(pwszSession, pAppDesc->pwszSessionName);
  316.                 }
  317.             }
  318.  
  319.             pHostNode->pwszSessionName = pwszSession;
  320.  
  321.             // Insert it onto the front of the list
  322.             pHostNode->pNext = g_pHostList ? g_pHostList->pNext : NULL;
  323.             g_pHostList = pHostNode;
  324.             pHostNode = NULL;
  325.  
  326. Break_ENUM_HOSTS_RESPONSE:
  327.             LeaveCriticalSection(&g_csHostList);
  328.  
  329.             if( pHostNode)
  330.             {
  331.                 SAFE_RELEASE(pHostNode->pHostAddress);
  332.  
  333.                 SAFE_DELETE(pHostNode->pAppDesc);
  334.  
  335.                 delete pHostNode;
  336.             }
  337.  
  338.             break;
  339.         }
  340.     }
  341.     return hr;
  342. }
  343.  
  344.  
  345.  
  346.  
  347. //-----------------------------------------------------------------------------
  348. // Name: EnumDirectPlayHosts()
  349. // Desc: Enumerates the hosts
  350. //-----------------------------------------------------------------------------
  351. HRESULT EnumDirectPlayHosts()
  352. {
  353.     HRESULT                 hr = S_OK;
  354.     WCHAR                   wszHost[128];
  355.     DPN_APPLICATION_DESC    dpAppDesc;
  356.     WCHAR*                  pwszURL = NULL;
  357.  
  358.     // Prompt for the hostname/ip
  359.     printf("\nPlease enter the IP address of host:\n");
  360.     wscanf(L"%ls", wszHost);
  361.  
  362.     if( FAILED( hr = CreateHostAddress( wszHost ) ) )
  363.     {
  364.         printf("Failed Creating Host Address:  0x%X\n", hr);
  365.         goto LCleanup;
  366.     }
  367.  
  368.     // Now set up the Application Description
  369.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  370.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  371.     dpAppDesc.guidApplication = g_guidApp;
  372.  
  373.     // We now have the host address so lets enum
  374.     if( FAILED( hr = g_pDP->EnumHosts(&dpAppDesc,            // pApplicationDesc
  375.                                         g_pHostAddress,     // pdpaddrHost
  376.                                         g_pDeviceAddress,   // pdpaddrDeviceInfo
  377.                                         NULL, 0,            // pvUserEnumData, size
  378.                                         4,                  // dwEnumCount
  379.                                         0,                  // dwRetryInterval
  380.                                         0,                  // dwTimeOut
  381.                                         NULL,               // pvUserContext
  382.                                         NULL,               // pAsyncHandle
  383.                                         DPNENUMHOSTS_SYNC ) ) )// dwFlags
  384.     {
  385.         printf("Failed Enumerating the Hosts:  0x%X\n", hr);
  386.         goto LCleanup;
  387.     }
  388.  
  389. LCleanup:
  390.     return hr;
  391. }
  392.  
  393.  
  394.  
  395.  
  396. //-----------------------------------------------------------------------------
  397. // Name: CreateDeviceAddress()
  398. // Desc: Creates a device address
  399. //-----------------------------------------------------------------------------
  400. HRESULT CreateDeviceAddress()
  401. {
  402.     HRESULT hr = S_OK;
  403.  
  404.     // Create our IDirectPlay8Address Device Address
  405.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  406.                                        CLSCTX_INPROC_SERVER,
  407.                                        IID_IDirectPlay8Address,
  408.                                        (LPVOID*) &g_pDeviceAddress ) ) )
  409.     {
  410.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  411.         goto LCleanup;
  412.     }
  413.     
  414.     // Set the SP for our Device Address
  415.     if( FAILED( hr = g_pDeviceAddress->SetSP(&CLSID_DP8SP_TCPIP ) ) )
  416.     {
  417.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  418.         goto LCleanup;
  419.     }
  420.  
  421. LCleanup:
  422.     return hr;
  423. }
  424.  
  425.  
  426.  
  427.  
  428. //-----------------------------------------------------------------------------
  429. // Name: CreateHostAddress()
  430. // Desc: Creates a host address
  431. //-----------------------------------------------------------------------------
  432. HRESULT CreateHostAddress(WCHAR* pwszHost)
  433. {
  434.     HRESULT hr = S_OK;
  435.  
  436.     // Create our IDirectPlay8Address Host Address
  437.     if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
  438.                                        CLSCTX_INPROC_SERVER,
  439.                                        IID_IDirectPlay8Address,
  440.                                        (LPVOID*) &g_pHostAddress ) ) )
  441.     {
  442.         printf("Failed Creating the IDirectPlay8Address Object:  0x%X\n", hr);
  443.         goto LCleanup;
  444.     }
  445.     
  446.     // Set the SP for our Host Address
  447.     if( FAILED( hr = g_pHostAddress->SetSP( &CLSID_DP8SP_TCPIP ) ) )
  448.     {
  449.         printf("Failed Setting the Service Provider:  0x%X\n", hr);
  450.         goto LCleanup;
  451.     }
  452.  
  453.     // Set the hostname into the address
  454.     if( FAILED( hr = g_pHostAddress->AddComponent(DPNA_KEY_HOSTNAME, pwszHost,
  455.                                                     2*(wcslen(pwszHost) + 1), /*bytes*/
  456.                                                     DPNA_DATATYPE_STRING ) ) )
  457.     {
  458.         printf("Failed Adding Hostname to Host Address:  0x%X\n", hr);
  459.         goto LCleanup;
  460.     }
  461.  
  462. LCleanup:
  463.     return hr;
  464. }
  465.  
  466.  
  467.  
  468.  
  469. //-----------------------------------------------------------------------------
  470. // Name: Host()
  471. // Desc: Host a DirectPlay session
  472. //-----------------------------------------------------------------------------
  473. HRESULT HostSession()
  474. {
  475.     HRESULT                 hr = S_OK;
  476.     DPN_APPLICATION_DESC    dpAppDesc;
  477.     WCHAR                   wszSession[128];
  478.  
  479.  
  480.     // Prompt the user for the session name
  481.     printf("\nPlease Enter a Session Name.\n");
  482.     wscanf(L"%ls", wszSession);
  483.  
  484.     // Now set up the Application Description
  485.     ZeroMemory(&dpAppDesc, sizeof(DPN_APPLICATION_DESC));
  486.     dpAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  487.     dpAppDesc.guidApplication = g_guidApp;
  488.     dpAppDesc.pwszSessionName = wszSession;
  489.  
  490.     // We are now ready to host the app
  491.     if( FAILED( hr = g_pDP->Host( &dpAppDesc,             // AppDesc
  492.                                   &g_pDeviceAddress, 1,   // Device Address
  493.                                   NULL, NULL,             // Reserved
  494.                                   NULL,                   // Player Context
  495.                                   0 ) ) )                 // dwFlags
  496.     {
  497.         printf("Failed Hosting:  0x%X\n", hr);
  498.         goto LCleanup;
  499.     }
  500.     else
  501.     {
  502.         printf("Currently Hosting...\n");
  503.     }
  504.  
  505. LCleanup:
  506.     return hr;
  507. }
  508.  
  509.  
  510.  
  511.  
  512. //-----------------------------------------------------------------------------
  513. // Name: ConnectToSession()
  514. // Desc: Connects to a DirectPlay session
  515. //-----------------------------------------------------------------------------
  516. HRESULT ConnectToSession()
  517. {
  518.     HRESULT                     hr = E_FAIL;
  519.     DPN_APPLICATION_DESC        dpnAppDesc;
  520.     IDirectPlay8Address*        pHostAddress = NULL;
  521.  
  522.     ZeroMemory(&dpnAppDesc, sizeof(DPN_APPLICATION_DESC));
  523.     dpnAppDesc.dwSize = sizeof(DPN_APPLICATION_DESC);
  524.     dpnAppDesc.guidApplication = g_guidApp;
  525.  
  526.     // Simply connect to the first one in the list
  527.     EnterCriticalSection(&g_csHostList);
  528.  
  529.     if( g_pHostList && SUCCEEDED(hr = g_pHostList->pHostAddress->Duplicate(&pHostAddress ) ) )
  530.     {
  531.         hr = g_pDP->Connect(&dpnAppDesc,        // pdnAppDesc
  532.                             pHostAddress,       // pHostAddr
  533.                             g_pDeviceAddress,   // pDeviceInfo
  534.                             NULL,               // pdnSecurity
  535.                             NULL,               // pdnCredentials
  536.                             NULL, 0,            // pvUserConnectData/Size
  537.                             NULL,               // pvPlayerContext
  538.                             NULL,               // pvAsyncContext
  539.                             NULL,               // pvAsyncHandle
  540.                             DPNCONNECT_SYNC);   // dwFlags
  541.  
  542.         if( FAILED( hr))
  543.             printf("Failed Connecting to Host:  0x%x\n", hr);
  544.     }
  545.     else
  546.     {
  547.         printf("Failed Duplicating Host Address:  0x%x\n", hr);
  548.     }
  549.  
  550.     LeaveCriticalSection(&g_csHostList);
  551.  
  552.     SAFE_RELEASE(pHostAddress);
  553.  
  554.     return hr;
  555. }
  556.  
  557.  
  558.  
  559.  
  560. //-----------------------------------------------------------------------------
  561. // Name: CleanupDirectPlay()
  562. // Desc: Cleanup DirectPlay
  563. //-----------------------------------------------------------------------------
  564. void CleanupDirectPlay()
  565. {
  566.     HOST_NODE* pHostNode = NULL;
  567.     HOST_NODE* pHostNodetmp = NULL;
  568.  
  569.     // Cleanup DirectPlay
  570.     if( g_pDP)
  571.         g_pDP->Close(0);
  572.  
  573.     // Clean up Host list
  574.     EnterCriticalSection(&g_csHostList);
  575.     
  576.     pHostNode = g_pHostList;
  577.     while( pHostNode != NULL )
  578.     {       
  579.         SAFE_RELEASE(pHostNode->pHostAddress);
  580.         SAFE_DELETE(pHostNode->pAppDesc);
  581.         SAFE_DELETE(pHostNode->pwszSessionName);
  582.  
  583.         pHostNodetmp = pHostNode;
  584.         pHostNode    = pHostNode->pNext;
  585.         SAFE_DELETE(pHostNodetmp);
  586.     }
  587.  
  588.     LeaveCriticalSection(&g_csHostList);
  589.  
  590.     SAFE_RELEASE(g_pDeviceAddress);
  591.     SAFE_RELEASE(g_pHostAddress);
  592.     SAFE_RELEASE(g_pDP);
  593.  
  594.     DeleteCriticalSection(&g_csHostList);
  595. }
  596.